

import java.net.URL;
import java.util.ResourceBundle;

import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane;
import javafx.util.Callback;

//@author A0096724W
public class MyController {
    
    /**********************
     * Private Variables
     **********************/
    private GUIController guiController;

    @FXML
    private ResourceBundle resources;

    @FXML
    private URL location;
    
    @FXML
    private Label autoSuggestStatus;

    @FXML
    private AnchorPane snoozeContainer;
    
    @FXML
    private Label deadlineStatus;

    @FXML
    private Label eventStatus;

    @FXML
    private Label miscStatus;
    
    @FXML
    private TextField textField;
    
    @FXML
    private TextArea textArea;

    @FXML
    private ListView<Task> timedList;
    
    @FXML
    private ListView<Task> deadlineList;
    
    @FXML
    private ListView<Task> floatingList;

    @FXML
    void addCommand(KeyEvent event) {
	//Control GUI response based on Key stroke entered by user
	guiController.invokeBehaviour(event);
    }
    
    @FXML
    void initialize() {
	assert autoSuggestStatus != null : "fx:id=\"autoSuggestStatus\" was not injected: check your FXML file 'Sample.fxml'.";
	assert deadlineList != null : "fx:id=\"deadlineList\" was not injected: check your FXML file 'Sample.fxml'.";
	assert deadlineStatus != null : "fx:id=\"deadlineStatus\" was not injected: check your FXML file 'Sample.fxml'.";
	assert eventStatus != null : "fx:id=\"eventStatus\" was not injected: check your FXML file 'Sample.fxml'.";
	assert floatingList != null : "fx:id=\"floatingList\" was not injected: check your FXML file 'Sample.fxml'.";
	assert miscStatus != null : "fx:id=\"miscStatus\" was not injected: check your FXML file 'Sample.fxml'.";
	assert snoozeContainer != null : "fx:id=\"snoozeContainer\" was not injected: check your FXML file 'Sample.fxml'.";
	assert textArea != null : "fx:id=\"textArea\" was not injected: check your FXML file 'Sample.fxml'.";
	assert textField != null : "fx:id=\"textField\" was not injected: check your FXML file 'Sample.fxml'.";
	assert timedList != null : "fx:id=\"timedList\" was not injected: check your FXML file 'Sample.fxml'.";
        
        initGUIController();
        initPrompt();
        setTextFieldFocused();
        
        initEventsList();
        initDeadlineList();
        initMiscList();
    }

    private void initMiscList() {
	//Set list to observe miscItems in Internal Memory
	floatingList.setItems(InternalMemory.getMiscTask());
        
        setMiscCellFactory();
        setMiscSelectionBehaviour();
    }

    private void setMiscSelectionBehaviour() {
	floatingList.getSelectionModel().selectedItemProperty()
        .addListener(new ChangeListener<Task>() {
          public void changed(ObservableValue<? extends Task> observable,
              Task oldValue, Task newValue) {            
            if (newValue != null) {
        	timedList.getSelectionModel().clearSelection();
            	deadlineList.getSelectionModel().clearSelection();
            }
          }
        });
    }

    private void setMiscCellFactory() {
	floatingList.setCellFactory(new Callback<ListView<Task>, ListCell<Task>>() {
            @Override public ListCell<Task> call(ListView<Task> list) {
        	MiscListCell floating = new MiscListCell();
        	floating.getStyleClass().add("floatListCell");
                return floating;
            }
        });
    }

    private void initDeadlineList() {
	//Set list to observe deadlineItems in Internal Memory
	deadlineList.setItems(InternalMemory.getDeadlineTask());
        
        setDeadlineCellFactory();
        setDeadlineSelectionBehaviour();
    }

    private void setDeadlineSelectionBehaviour() {
	deadlineList.getSelectionModel().selectedItemProperty()
        .addListener(new ChangeListener<Task>() {
          public void changed(ObservableValue<? extends Task> observable,
              Task oldValue, Task newValue) {
            if (newValue != null) {
        	timedList.getSelectionModel().clearSelection();
            	floatingList.getSelectionModel().clearSelection();
            }
          }
        });
    }

    private void setDeadlineCellFactory() {
	deadlineList.setCellFactory(new Callback<ListView<Task>, ListCell<Task>>() {
            @Override public ListCell<Task> call(ListView<Task> list) {
        	DeadlineListCell deadline = new DeadlineListCell();
        	deadline.getStyleClass().add("deadListCell");
                return deadline;
            }
        });
    }

    private void initEventsList() {
	//Set list to observe eventItems in Internal Memory
	timedList.setItems(InternalMemory.getEventTask());
        
        setEventCellFactory();
        setEventSelectionBehaviour();
    }

    private void setEventSelectionBehaviour() {
	timedList.getSelectionModel().selectedItemProperty()
        .addListener(new ChangeListener<Task>() {
          public void changed(ObservableValue<? extends Task> observable,
              Task oldValue, Task newValue) {
            if (newValue != null) {
        	deadlineList.getSelectionModel().clearSelection();
            	floatingList.getSelectionModel().clearSelection();
            }
          }
        });
    }

    private void setEventCellFactory() {
	timedList.setCellFactory(new Callback<ListView<Task>, ListCell<Task>>() {
            @Override public ListCell<Task> call(ListView<Task> list) {
        	EventListCell timed = new EventListCell();
        	timed.getStyleClass().add("timedListCell");
                return timed;
            }
        });
    }

    private void setTextFieldFocused() {
	Platform.runLater(new Runnable() {
            @Override
            public void run() {
                textField.requestFocus();
            }
       });
    }

    private void initPrompt() {
	textField.setPromptText("Enter command here");
        textArea.setPromptText("Feedback appears here");
    }

    private void initGUIController() {
	guiController = new GUIController(textField, textArea, timedList, deadlineList, floatingList, 
        	eventStatus, deadlineStatus, miscStatus, autoSuggestStatus);
    }

}
